package pl.edu.agh.jemo.evolution.operator.mutation.impl;

import javax.swing.JPanel;

import pl.edu.agh.jemo.evolution.common.JemoRandom;
import pl.edu.agh.jemo.gui.panels.mutation.BalancedMutationConfigurationPanel;

/**
 * Extends Classic Mutation with possibility to verify which bits of specimens genotype are changed.
 * Allows to use different chance for exponent and sign bits modification, which allows to generate specimen more simmilar to parent.
 * It uses ClassicMutation technics to verify specimen correctness after mutation.
 * 
 * @author Marcin Zbijowski
 *
 */
public class BalancedMutation extends ClassicMutation {

	/**
	 * Chance for single bit of genotypes exponent, to be changed by operator.
	 */
	protected Double strongMutationChance = .01;
	
	/**
	 * Generates list of bits to be switched as a result of mutation.
	 * A list is represented as long number, which has the same bit's number as double (on which genotype is encoded) in java. Every bit set to one on returned value results in changed bit of parent specimen.
	 * Chance to modify any of mantisa's bit is specified by mutationChance parameter and chance to modify exponents or sign bit depends on strongMutationChance parameter.
	 */
	@Override
	protected long encodeMutation() {
		long result = 0;
		int i = 0;
		for (i = 0; i < 52; i++) {
			if (JemoRandom.getRandom().nextDouble() < mutationChance) {
				result += Math.pow(2.0, i);
			}
		}
		for (i = 52; i < 64; i++) {
			if (JemoRandom.getRandom().nextDouble() < strongMutationChance) {
				result += Math.pow(2.0, i);
			}
		}
		if (JemoRandom.getRandom().nextDouble() < mutationChance) {
			result += Math.pow(2.0, 52);
		}
		return result;
	}

	/**
	 * Returns chance to modify exponent of genotype of mutated specimen.
	 * 
	 * @return Value of strongMutationChance parameter.
	 */
	public Double getStrongMutationChance() {
		return strongMutationChance;
	}

	/**
	 * Sets chance to modify exponent of genotype of mutated specimen.
	 * @param strongMutationChance New value of strongMutationChance parameter
	 */
	public void setStrongMutationChance(Double strongMutationChance) {
		this.strongMutationChance = strongMutationChance;
	}
	
	/**
	 * Returns configuration panel being extension of JPanel instance.
	 * Returned panel is displayed by graphical user interface allowing user to confgiure mutation.
	 * This method may return null if no configuration for operator is possible.
	 * 
	 * @return Instance of JPanel with initialized components prepared to configure objects properties.
	 */
	@Override
	public JPanel getConfigPanel() {
		return new BalancedMutationConfigurationPanel(this);
	}
	
	/**
	 * Returns String object containing description of mutation configuration in readable form as a summary.
	 * 
	 * @return String description of object configuration.
	 */
	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder();
		sb.append(super.toString());
		sb.append("Strong mutation chance: " + strongMutationChance + "\n");
		return sb.toString();
	}

}
